#include "menu.h"
#include <cstdlib>

using namespace std;

void Menu::Run(){

    try
    {
        lib.fillBooksFromFile("Books.txt");
        lib.fillMembersFromFile("Members.txt");
        lib.fillRentalsFromFile("Rentals.txt");
    }
    catch(Library::Exceptions e)
    {
        if( e == Library::B_FILEDONOTEXIST) cout << "The input file of books isn't exist!\n";
        if( e == Library::M_FILEDONOTEXIST) cout << "The input file of members isn't exist!\n";
        if( e == Library::R_FILEDONOTEXIST) cout << "The input file of rentals isn't exist!\n";
    }

    int n = 0;
    do {
        MenuWrite();
        n = read_int("\n>>>>","Please enter a number from 0 to 12!",toTwelve);
        switch(n) {
            case 1: { // Add new Book
                string tmp;
                string attr01, attr02, attr04, attr06, attr08;
                int attr03, attr05, attr07;

                system("cls");
                cout << "Please give the name of author: ";
                getline(cin, attr01);
                cout << "Please give the title of book: ";
                getline(cin, attr02);
                attr03 = read_int("Please give the date of writing: ","Please enter a number.");
                cout << "Please give the name of publisher: ";
                getline(cin, attr04);
                attr05 = read_int("Please give the date of publication: ","Please enter a number.");
                cout << "Please give the ISBN of book: ";
                getline(cin, attr06);
                attr07 = read_int("Please give the number of books: ","Please enter a number.");
                attr08 = read_string("Is rent? ","Please enter Yes or No.",YON);
                system("cls");

                Book b(attr01, attr02, attr03, attr04, attr05, attr06, attr07, (attr08 == "Yes"));

                try
                {
                    lib.addBook(b);
                }
                catch(Library::Exceptions e)
                {
                    if( e == Library::B_DATA_REDUNDANCY)
                    {
                        cout << "The book is already exist in the database.\n";
                        system("pause");
                    }
                }

                system("cls");
                break;
                }
            case 2: { // Delete Book
                string id;

                system("cls");
                cout << "Please give the book id: ";
                cin >> id;
                system("cls");

                try
                {
                    lib.delBook(id);
                }
                catch(Library::Exceptions e)
                {
                    if( e == Library::B_DATA_DOESNOTEXIST)
                    {
                        cout << "The book does not exist in the database.\n";
                        system("pause");
                    }
                }

                system("cls");
                break;
                }
            case 3: { // List of Books
                system("cls");
                lib.listBooks();
                system("pause");
                system("cls");
                break;
                }
            case 4: { // Search Book
                int x;
                string s, tmp;

                system("cls");
                cout << "[ SEARCH BOOKS ]\n\n";
                cout << " 1. - By Author" << endl;
                cout << " 2. - By Title" << endl;
                cout << " 3. - By Id" << endl;
                cout << " 4. - Outstanding" << endl;
                x = read_int("\n>>>>","Please enter a number from 1 to 4!",toFour);
                system("cls");

                switch(x) {
                    case 1: {
                        cout << "Please enter the author of book: ";
                        getline(cin, s);
                        lib.searchBook("Author", s);
                        break;
                        }
                    case 2: {
                        cout << "Please enter the title of book: ";
                        getline(cin, s);
                        lib.searchBook("Title", s);
                        break;
                        }
                    case 3: {
                        cout << "Please enter the id of book: ";
                        getline(cin, s);
                        lib.searchBook("Id", s);
                        break;
                        }
                    case 4: {
                        lib.searchBook("Out","none");
                        }
                }

                system("pause");
                system("cls");
                break;
                }
            case 5: { // Add new Member
                stringstream ss;
                string s, t;

                system("cls");
                ss.clear();
                //cout << "Type: "; //getline(cin, t);
                t = read_string("Type: ","Please enter Teacher, Student, SOOU, or Other.",who);
                cout << "Name: "; getline(cin, s); ss << s << endl;
                cout << "Address: "; getline(cin, s); ss << s << endl;
                cout << "Id: "; getline(cin, s); ss << s << endl;
                cout << "Availability: "; getline(cin, s); ss << s << endl;
                cout << "Balance: "; getline(cin, s); ss << s << endl;
                system("cls");

                try
                {
                    lib.addMember(t, ss);
                }
                catch(Library::Exceptions e)
                {
                    if( e == Library::M_DATA_REDUNDANCY)
                    {
                        cout << "The member is already exist in the database.\n";
                        system("pause");
                    }
                }

                system("cls");
                break;
                }
            case 6: { // Delete Member
                string id;

                system("cls");
                cout << "Please give the member id: ";
                cin >> id;
                system("cls");

                try
                {
                    lib.delMember(id);
                }
                catch(Library::Exceptions e)
                {
                    if( e == Library::M_DATA_DOESNOTEXIST)
                    {
                        cout << "The member does not exist in the database.\n";
                        system("pause");
                    }
                }

                system("cls");
                break;
                }
            case 7: { // List of Members
                system("cls");
                lib.listMembers();
                system("pause");
                system("cls");
                break;
                }
            case 8: { // Search Member
                int x;
                string s, tmp;

                system("cls");
                cout << "[ SEARCH BOOKS ]\n\n";
                cout << " 1. - By Name" << endl;
                cout << " 2. - By Id" << endl;
                cout << " 3. - Students" << endl;
                cout << " 4. - Teacher" << endl;
                cout << " 5. - Member of other University" << endl;
                cout << " 6. - Other" << endl;
                cout << " 7. - Delay of the members" << endl;
                x = read_int("\n>>>>","Please enter a number from 1 to 7!",toSeven);
                system("cls");

                switch(x) {
                    case 1: {
                        cout << "Please enter the name of member: ";
                        getline(cin, s);
                        lib.searchMember("Name", s);
                        break;
                        }
                    case 2: {
                        cout << "Please enter the id of member: ";
                        getline(cin, s);
                        lib.searchMember("Id", s);
                        break;
                        }
                    case 3: {
                        lib.searchMember("Student","none");
                        break;
                        }
                    case 4: {
                        lib.searchMember("Teacher","none");
                        break;
                        }
                    case 5: {
                        lib.searchMember("SOOU","none");
                        break;
                        }
                    case 6: {
                        lib.searchMember("Other","none");
                        break;
                        }
                    case 7: {
                        lib.searchMember("Late","none");
                        break;
                        }
                }

                system("pause");
                system("cls");
                break;
                }
            case 9: { // Payment
                string id;
                int v;

                system("cls");
                cout << "Please give the id of member: ";
                cin >> id;
                cout << "Please give value of inpayment: ";
                cin >> v;
                system("cls");

                try
                {
                    lib.payment(id, v);
                }
                catch(Library::Exceptions e)
                {
                    if( e == Library::M_DATA_DOESNOTEXIST)
                    {
                        cout << "The member does not exist in the database.\n";
                        system("pause");
                    }
                }

                system("cls");
                break;
                }
            case 10: { // Loan
                string attr01, attr02;

                system("cls");
                cout << "Please give the id of member: ";
                cin >> attr02;
                cout << "Please give the id of book: ";
                cin >> attr01;
                system("cls");

                Rental r(attr01, attr02);

                try
                {
                    lib.addRentalOut(r);
                }
                catch(Library::Exceptions e)
                {
                    if(e == Library::B_DATA_DOESNOTEXIST) cout << "The book can not be borrowed or found in the database.\n";
                    if(e == Library::ISNOTRENT) cout << "The book isn't for loan.\n";
                    if(e == Library::M_DATA_DOESNOTEXIST) cout << "The member does not exist in the database.\n";
                    if(e == Library::OWE) cout << "The member has overdue.\n";
                    system("pause");
                }

                system("cls");
                break;
                }
            case 11: { // Back
                string attr01, attr02;

                system("cls");
                cout << "Please give the id of member: ";
                cin >> attr02;
                cout << "Please give the id of book: ";
                cin >> attr01;
                system("cls");

                Rental r(attr01, attr02);

                try
                {
                    lib.addRentalIn(r);
                }
                catch(Library::Exceptions e)
                {
                    if(e == Library::R_DATA_DOESNOTEXIST)
                        {
                            cout << "This loan does not exist in the database.\n";
                            system("pause");
                        }
                }

                system("cls");
                break;
                }
            case 12: { // Search by member
                string s;

                system("cls");
                cout << "Please enter the id of member: ";
                getline(cin, s);
                system("cls");

                try
                {
                    lib.searchRental(s);
                }
                catch(Library::Exceptions e)
                {
                    if(e == Library::M_DATA_DOESNOTEXIST) cout << "The member does not exist in the database.\n";
                }

                system("pause");
                system("cls");
                break;
                }
            case 0: { // SAVE
                lib.saveDataOfBooks("Books.txt");
                lib.saveDataOfMembers("Members.txt");
                lib.saveDataOfRentals("Rentals.txt");
                break;
                }
        }
    } while(n!=0);
}

void Menu::MenuWrite(){
    cout << "[ BOOKS ]\n\n";
    cout << " 1. - Add new Book" << endl;
    cout << " 2. - Delelete Book" << endl;
    cout << " 3. - List of Books" << endl;
    cout << " 4. - Search Books" << endl;
    cout << "\n[ MEMBERS ]\n\n";
    cout << " 5. - Add new Member" << endl;
    cout << " 6. - Delete Member" << endl;
    cout << " 7. - List of Members" << endl;
    cout << " 8. - Search Member" << endl;
    cout << " 9. - Payment" << endl;
    cout << "\n[ RENTALS ]\n\n";
    cout << "10. - Loan" << endl;
    cout << "11. - Back" << endl;
    cout << "12. - Search" << endl << endl;
    cout << " 0. - Quit" << endl;
}

bool all(int n) { return true; }
bool toTwelve(int n) { return (n >= 0 && n < 13); }
bool toSeven(int n) { return (n >= 1 && n < 8); }
bool toFour(int n) { return (n >= 1 && n < 5); }
bool who(string& n) { return ( n == "Teacher" ||
                                     n == "Student" ||
                                     n == "SOOU" ||
                                     n == "Other");}

bool YON(string& n) { return ( n == "Yes" || n == "No"); }

int read_int(const string &msg, const string &err, bool check(int)){
    int n;
    bool hiba;
    string tmp;
    do{
        cout << msg;
        string str;
        cin >> n;
        hiba = cin.fail() || !check(n);
        if(hiba) {
            cout << err << endl;
            cin.clear(); getline(cin, tmp);
        }
    }while(hiba);
    getline(cin, tmp);

    return n;
}

std::string read_string(const string &msg, const string &err, bool check(string&)){
    string n;
    bool hiba;
    string tmp;
    do{
        cout << msg;
        string str;
        cin >> n;
        hiba = cin.fail() || !check(n);
        if(hiba) {
            cout << err << endl;
            cin.clear(); getline(cin, tmp);
        }
    }while(hiba);
    getline(cin, tmp);

    return n;
}
